#include "vec4.h"


    vec4 vec4::Forward( 0.0f, 0.0f, -1.0f, 1.0f);
    vec4 vec4::Zero(    0.0f, 0.0f, 0.0f, 1.0f);
    vec4 vec4::Up(      0.0f, 1.0f, 0.0f, 1.0f);
    vec4 vec4::Right(   1.0f, 0.0f, 0.0f, 1.0f);

/****************************************
/*          Public
/****************************************/

    /****************************************
    /*          Constructors
    /****************************************/

    vec4::vec4()                                        : x(0), y(0), z(0), w(0){}
    vec4::vec4(float aX)                                : x(aX), y(0), z(0), w(0){}
    vec4::vec4(float aX, float aY)                      : x(aX), y(aY), z(0), w(0){}
    vec4::vec4(float aX, float aY, float aZ)            : x(aX), y(aY), z(aZ), w(0){}
    vec4::vec4(float aX, float aY, float aZ, float aW)  : x(aX), y(aY), z(aZ), w(aW){}
    vec4::vec4(const vec4 & vec){
        x=vec.x;
        y=vec.y;
        z=vec.z;
        w=vec.w;
    }

/***************************************************************
/*              Operator overload
/***************************************************************/

void vec4::operator+=(const vec4 & v){
  x+=   v.x;
  y+=   v.y;
  z+=   v.z;
  w+=   v.w;
}

void vec4::operator-=(const vec4 & v){
    x-=   v.x;
    y-=   v.y;
    z-=   v.z;
    w-=   v.w;
}

vec4  vec4::operator+(const vec4 & v){
    vec4 vec(*this);

        vec.x+=   v.x;
        vec.y+=   v.y;
        vec.z+=   v.z;
        vec.w+=   v.w;

    return vec;
}


vec4  vec4::operator-(const vec4 & v){
    vec4 vec(*this);

        vec.x-=   v.x;
        vec.y-=   v.y;
        vec.z-=   v.z;
        vec.w-=   v.w;

    return vec;
}

vec4 vec4::operator *(const vec4 & v){
    vec4 vec(*this);

        vec.x=vec.x*v.x;
        vec.y=vec.y*v.y;
        vec.z=vec.z*v.z;
        vec.w=vec.w*v.w;

    return vec;
}

vec4 vec4::operator*(float val){
    vec4 vec(*this);

        vec.x=vec.x*val;
        vec.y=vec.y*val;
        vec.z=vec.z*val;
        vec.w=vec.w*val;

    return vec;
}

vec4 vec4::operator /(float val){
    vec4 vec(*this);

        vec.x=vec.x/val;
        vec.y=vec.y/val;
        vec.z=vec.z/val;
        vec.w=vec.w/val;

    return vec;
}

vec4 & vec4::operator=(const vec4 & v){
    x=v.x;
    y=v.y;
    z=v.z;
    w=v.w;

    return * this;
}


    /******************************
    /*          Methods
    /******************************/

vec4 vec4::TurnAround(float teta, float alpha, float radius, vec4 point){
    vec4 vec ;



    vec.z   =   sin(alpha)*cos(teta)*radius;
    vec.y   =   sin(teta)*radius;
    vec.x   =   cos(alpha)*cos(teta)*radius;

    return vec+point;
}

vec4 vec4::Interpolate(vec4 v1, vec4 v2, float t){
    return v1+((v2-v1)*t);
}

/*! @brief Return the vector as a 4 float array     */
float * vec4::Array(){
    float * array = new float[4];
    array[0]=x; array[1]=y; array[2]=z; array[3]=w;

    return array;
}

vec4 vec4::Normalize(){
    double length = Magnitude();

    vec4 * out;

    if(length==0){
        out= new vec4(0.0, 0.0, 0.0);
    }else{
        out= new vec4(x/length,y/length, z/length);
    }

    return *out;
}

vec4 vec4::Inverse(){
    vec4 vec (0.0,0.0,0.0);

   vec.x=1;

    return vec;
}

float vec4::Magnitude(){
    float sum=0;

    sum+=pow(x,2);
    sum+=pow(y,2);
    sum+=pow(z,2);
    //sum+=pow(w,2);

    return sqrt(sum);
}

void vec4::Print(){
    printf(" %f %f %f %f \n",x,y,z,w);
}

/*

vec4 & vec4::operator+(const vec4 & argVector)
{
    vec4 vec;
        x+=argVector.x;
        y+=argVector.y;
        z+=argVector.z;

        return *this;
}


bool vec4::operator ==(const vec4 & argV)
{
    if(x==argV.x)
    {
        if(y==argV.y)
        {
            if(z==argV.z)
            {
                return true;
            }
        }
    }

    return false;
}



*/
/***********************************************************************/
/*                      Méthodes                                       */
/***********************************************************************/
/*
void vec4::Set(float aX, float aY, float aZ)
{
    x=aX;
    y=aY;
    z=aZ;
 }

 void vec4::Set(float * aF)
{
    x=aF[0];
    y=aF[1];
    z=aF[2];
 }


float * vec4::ToArray()
{
    float * fa= new float [3];	//fa pour "float array"
        fa[0]=x;
        fa[1]=y;
        fa[2]=z;
    return fa;
}

int vec4::Collide(vec4 aVertex)
{
    vec4 u=CalculVecteur(*this,aVertex);

    if(u.Norme()<1)
    {
        return true;
    }
    return false;
}


*/
/***********************************************************************/
/*                      Méthodes statiques                             */
/***********************************************************************/
/*
float vec4::Angle(vec4 u, vec4 v)
{

    return asin(
                    (vec4::ProduitVectoriel(u,v)).z
                    /
                   (u.Norme()*v.Norme())
                );
}
*/

float vec4::Dot(vec4 u, vec4 v){
    return (float)((u.x*v.x)+(u.y*v.y)+(u.z*v.z));
}

vec4  vec4::Cross(vec4 u, vec4 v){
    vec4 * tempVector= new vec4(0.0,0.0,0.0);

    tempVector->x=  (u.y*v.z)-(v.y*u.z);
    tempVector->y=  (u.z*v.x)-(v.z*u.x);
    tempVector->z=  (u.x*v.y)-(v.x*u.y);

    return *tempVector;
}

/*
vec4 vec4::IntersectionPlan(vec4 u, vec4 lineVertex, vec4 normalPlane, vec4 planeVertex)
{
    printf("u :  x : %f, y: %f, z : %f \n",u.x(),u.y(),u.z());
    printf("vLine : x : %f, y: %f, z : %f \n",lineVertex.x(),lineVertex.y(),lineVertex.z());
    printf("vplan : x : %f, y: %f, z : %f \n",planeVertex.x(),planeVertex.y(),planeVertex.z());

    vec4 v(planeVertex.x()-lineVertex.x(), planeVertex.y()-lineVertex.y(), planeVertex.z()-lineVertex.z());

    printf("vLine-plan : x : %f, y: %f, z : %f \n",v.x(),v.y(),v.z());
    float val;

    vec4 vNormal=u.Normalize();
    printf("uNormal :  x : %f, y: %f, z : %f \n",vNormal.x(),vNormal.y(),vNormal.z());

    printf("produitSclaire plane.v %f \n",ProduitScalaire(normalPlane,v));
    printf("produitSclaire plane.u %f \n",ProduitScalaire(normalPlane,u));

    val= ProduitScalaire(normalPlane,v)/ProduitScalaire(normalPlane,u);

    printf("val : %f \n",val);
    return u*val;
}
*/


